package cn.iocoder.yudao.module.erp.service.exchange.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.erp.controller.admin.exchange.vo.item.ErpExchangeOrderItemBaseVO;
import cn.iocoder.yudao.module.erp.controller.admin.exchange.vo.order.ErpExchangeOrderCreateReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.exchange.vo.order.ErpExchangeOrderPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.exchange.vo.order.ErpExchangeOrderUpdateReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.exchange.ErpExchangeOrderDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.exchange.ErpExchangeOrderItemDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO;
import cn.iocoder.yudao.module.erp.dal.mysql.exchange.ErpExchangeOrderItemMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.exchange.ErpExchangeOrderMapper;
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
import cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.erp.service.exchange.ErpExchangeOrderService;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;

/**
 * ERP 旧料兑换订单 Service 实现类
 */
@Service
@Validated
@Slf4j
public class ErpExchangeOrderServiceImpl implements ErpExchangeOrderService {

    private static final String ORDER_NO_PREFIX = "EX";

    @Resource
    private ErpExchangeOrderMapper exchangeOrderMapper;
    @Resource
    private ErpExchangeOrderItemMapper exchangeOrderItemMapper;

    @Resource
    private ErpCustomerService customerService;
    @Resource
    private ErpProductService productService;
    @Resource
    private ErpStockService stockService;
    @Resource
    private AdminUserApi adminUserApi;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createExchangeOrder(ErpExchangeOrderCreateReqVO createReqVO) {
        // 1. 校验客户
        ErpCustomerDO customer = customerService.getCustomer(createReqVO.getCustomerId());
        if (customer == null) {
            throw exception(ErrorCodeConstants.CUSTOMER_NOT_EXISTS);
        }
        if (ObjectUtil.notEqual(customer.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
            throw exception(ErrorCodeConstants.CUSTOMER_NOT_ENABLE, customer.getName());
        }

        // 2. 生成订单流水号
        String no = ORDER_NO_PREFIX + LocalDateTime.now().toString();
        // TODO: 基于redis自增生成编号

        // 3. 校验产品，计算金额
        List<ErpExchangeOrderItemDO> exchangeOrderItems = validateProductItems(createReqVO.getItems());

        // 4. 保存订单
        ErpExchangeOrderDO exchangeOrder = BeanUtils.toBean(createReqVO, ErpExchangeOrderDO.class);
        exchangeOrder.setNo(no);
        exchangeOrder.setStatus(ErpAuditStatus.DRAFT.getStatus());
        exchangeOrder.setCustomerName(customer.getName());
        exchangeOrderMapper.insert(exchangeOrder);

        // 5. 保存订单项
        for (ErpExchangeOrderItemDO item : exchangeOrderItems) {
            item.setOrderId(exchangeOrder.getId());
            exchangeOrderItemMapper.insert(item);
        }
        return exchangeOrder.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateExchangeOrder(ErpExchangeOrderUpdateReqVO updateReqVO) {
        // 1.1 校验存在
        ErpExchangeOrderDO exchangeOrder = validateExchangeOrderExists(updateReqVO.getId());
        // 1.2 校验状态
        if (ObjectUtil.notEqual(exchangeOrder.getStatus(), ErpAuditStatus.DRAFT.getStatus())) {
            throw exception(EXCHANGE_ORDER_UPDATE_FAIL_APPROVE, exchangeOrder.getNo());
        }

        // 2. 校验客户
        ErpCustomerDO customer = customerService.getCustomer(updateReqVO.getCustomerId());
        if (customer == null) {
            throw exception(CUSTOMER_NOT_EXISTS);
        }
        if (ObjectUtil.notEqual(customer.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
            throw exception(CUSTOMER_NOT_ENABLE, customer.getName());
        }

        // 3. 校验产品，计算金额
        List<ErpExchangeOrderItemDO> exchangeOrderItems = validateProductItems(updateReqVO.getItems());

        // 4. 更新订单
        ErpExchangeOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpExchangeOrderDO.class);
        updateObj.setCustomerName(customer.getName());
        exchangeOrderMapper.updateById(updateObj);

        // 5.1 删除旧的订单项
        exchangeOrderItemMapper.deleteByOrderId(updateReqVO.getId());
        // 5.2 插入新的订单项
        for (ErpExchangeOrderItemDO item : exchangeOrderItems) {
            item.setOrderId(updateReqVO.getId());
            exchangeOrderItemMapper.insert(item);
        }
    }

    @Override
    public void updateExchangeOrderStatus(Long id, Integer status) {
        // 校验存在
        ErpExchangeOrderDO exchangeOrder = validateExchangeOrderExists(id);
        // 更新状态
        exchangeOrderMapper.updateById(new ErpExchangeOrderDO().setId(id).setStatus(status));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteExchangeOrder(Long id) {
        // 1.1 校验存在
        ErpExchangeOrderDO exchangeOrder = validateExchangeOrderExists(id);
        // 1.2 校验状态
        if (ObjectUtil.notEqual(exchangeOrder.getStatus(), ErpAuditStatus.DRAFT.getStatus())) {
            throw exception(EXCHANGE_ORDER_DELETE_FAIL_APPROVE, exchangeOrder.getNo());
        }

        // 2. 删除
        exchangeOrderMapper.deleteById(id);
        exchangeOrderItemMapper.deleteByOrderId(id);
    }

    @Override
    public ErpExchangeOrderDO getExchangeOrder(Long id) {
        return exchangeOrderMapper.selectById(id);
    }

    @Override
    public List<ErpExchangeOrderDO> getExchangeOrderList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return exchangeOrderMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<ErpExchangeOrderDO> getExchangeOrderPage(ErpExchangeOrderPageReqVO pageReqVO) {
        return exchangeOrderMapper.selectPage(pageReqVO);
    }

    @Override
    public List<ErpExchangeOrderItemDO> getExchangeOrderItemListByOrderId(Long orderId) {
        return exchangeOrderItemMapper.selectListByOrderId(orderId);
    }

    @Override
    public List<ErpExchangeOrderItemDO> getExchangeOrderItemListByOrderIds(List<Long> orderIds) {
        if (CollUtil.isEmpty(orderIds)) {
            return Collections.emptyList();
        }
        return exchangeOrderItemMapper.selectListByOrderIds(orderIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approveExchangeOrder(Long id) {
        // 1.1 校验存在
        ErpExchangeOrderDO exchangeOrder = validateExchangeOrderExists(id);
        // 1.2 校验状态
        if (ObjectUtil.notEqual(exchangeOrder.getStatus(), ErpAuditStatus.DRAFT.getStatus())) {
            throw exception(EXCHANGE_ORDER_APPROVE_FAIL);
        }

        // 2. 更新状态
//        exchangeOrderMapper.updateById(new ErpExchangeOrderDO().setId(id)
//                .setStatus(ErpAuditStatus.APPROVED.getStatus())
//                .setApproveBy(adminUserApi.getUser(adminUserApi.getLoginUserId()).getNickname())
//                .setApproveTime(LocalDateTime.now()));

        // 3. 更新库存
        // 3.1 查询订单项
        List<ErpExchangeOrderItemDO> items = exchangeOrderItemMapper.selectListByOrderId(id);
        if (CollUtil.isEmpty(items)) {
            return;
        }
        
        // 3.2 更新库存
        for (ErpExchangeOrderItemDO item : items) {
//            if (ErpExchangeItemTypeEnum.OLD_MATERIAL.getType().equals(item.getType())) {
//                // 旧料入库
//                stockService.updateStockCount(item.getProductId(), null,
//                        item.getCount(), ErpBizTypeEnum.EXCHANGE_IN.getType(), String.valueOf(id));
//            } else if (ErpExchangeItemTypeEnum.EXCHANGE_PRODUCT.getType().equals(item.getType())) {
//                // 兑换产品出库
//                stockService.updateStockCount(item.getProductId(), null,
//                        item.getCount().negate(), ErpBizTypeEnum.EXCHANGE_OUT.getType(), String.valueOf(id));
//            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void disapproveExchangeOrder(Long id) {
        // 1.1 校验存在
        ErpExchangeOrderDO exchangeOrder = validateExchangeOrderExists(id);
        // 1.2 校验状态
//        if (ObjectUtil.notEqual(exchangeOrder.getStatus(), ErpAuditStatus.APPROVED.getStatus())) {
//            throw exception(EXCHANGE_ORDER_PROCESS_FAIL);
//        }

        // 2. 更新状态
        exchangeOrderMapper.updateById(new ErpExchangeOrderDO().setId(id)
                .setStatus(ErpAuditStatus.DRAFT.getStatus())
                .setApproveBy(null).setApproveTime(null));

        // 3. 回滚库存
        // 3.1 查询订单项
        List<ErpExchangeOrderItemDO> items = exchangeOrderItemMapper.selectListByOrderId(id);
        if (CollUtil.isEmpty(items)) {
            return;
        }
        
        // 3.2 更新库存
//        for (ErpExchangeOrderItemDO item : items) {
//            if (ErpExchangeItemTypeEnum.OLD_MATERIAL.getType().equals(item.getType())) {
//                // 旧料出库（回滚）
//                stockService.updateStockCount(item.getProductId(), null,
//                        item.getCount().negate(), ErpBizTypeEnum.EXCHANGE_IN.getType(), String.valueOf(id));
//            } else if (ErpExchangeItemTypeEnum.EXCHANGE_PRODUCT.getType().equals(item.getType())) {
//                // 兑换产品入库（回滚）
//                stockService.updateStockCount(item.getProductId(), null,
//                        item.getCount(), ErpBizTypeEnum.EXCHANGE_OUT.getType(), String.valueOf(id));
//            }
//        }
    }

    /**
     * 校验兑换订单是否存在
     *
     * @param id 订单编号
     * @return 兑换订单
     */
    private ErpExchangeOrderDO validateExchangeOrderExists(Long id) {
        ErpExchangeOrderDO exchangeOrder = exchangeOrderMapper.selectById(id);
        if (exchangeOrder == null) {
            throw exception(EXCHANGE_ORDER_NOT_EXISTS);
        }
        return exchangeOrder;
    }

    /**
     * 校验产品项目
     *
     * @param items 产品项目列表
     * @return 订单项列表
     */
    private List<ErpExchangeOrderItemDO> validateProductItems(List<ErpExchangeOrderItemBaseVO> items) {
        // 1. 转换成 DO 对象
        List<ErpExchangeOrderItemDO> itemDOs = BeanUtils.toBean(items, ErpExchangeOrderItemDO.class);

        // 2. 校验产品存在
//        Map<Long, ErpProductDO> productMap = productService.getProductMap(
//                CollectionUtils.convertSet(items, ErpExchangeOrderItemDO::getProductId));
        // 3. 遍历处理每个项目
        BigDecimal oldMaterialTotalPrice = BigDecimal.ZERO;
        BigDecimal exchangeProductTotalPrice = BigDecimal.ZERO;
//        for (int i = 0; i < itemDOs.size(); i++) {
//            ErpExchangeOrderItemDO item = itemDOs.get(i);
//            // 3.1 校验产品
//            ErpProductDO product = productMap.get(item.getProductId());
//            if (product == null) {
//                throw exception(PRODUCT_NOT_EXISTS);
//            }
//            if (ObjectUtil.notEqual(product.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
//                throw exception(PRODUCT_NOT_ENABLE, product.getName());
//            }
//
//            // 3.2 设置排序
//            item.setSort(i);
//
//            // 3.3 计算金额
//            if (ErpExchangeItemTypeEnum.OLD_MATERIAL.getType().equals(item.getType())) {
//                oldMaterialTotalPrice = MoneyUtils.add(oldMaterialTotalPrice, item.getPrice());
//            } else if (ErpExchangeItemTypeEnum.EXCHANGE_PRODUCT.getType().equals(item.getType())) {
//                exchangeProductTotalPrice = MoneyUtils.add(exchangeProductTotalPrice, item.getPrice());
//            }
//        }
//
//        // 4. 计算差价
//        BigDecimal priceDifference = MoneyUtils.subtract(exchangeProductTotalPrice, oldMaterialTotalPrice);
        
        return itemDOs;
    }
} 